package com.fshows.leshuapay.sdk.client.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fshows.leshuapay.sdk.client.LeshuaMerchantBillClient;
import com.fshows.leshuapay.sdk.exception.LeshuaException;
import com.fshows.leshuapay.sdk.request.LeshuaBizRequest;
import com.fshows.leshuapay.sdk.response.bill.LeshuaBillBaseResponse;
import com.fshows.leshuapay.sdk.response.bill.LeshuaPage;
import com.fshows.leshuapay.sdk.util.ReqSerialNoUtil;
import com.fshows.leshuapay.sdk.util.SignUtil;
import com.fshows.leshuapay.sdk.util.ValidateUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.util.List;

/**
 * @author huanghai
 * @version 1.0 LeshuaMerchantBillClientImpl
 * @date 2021/11/23 16:04
 */
@Slf4j
@Data
public class LeshuaMerchantBillClientImpl implements LeshuaMerchantBillClient {
    /**
     * 从connectManager获取Connection 超时时间
     */
    private static final int CONNECTION_REQUEST_TIMEOUT = 10000;

    /**
     * 读取数据的超时时间
     */
    private static final int SOCKET_TIMEOUT = 10000;

    /**
     * 连接超时时间
     */
    private static final int CONNECT_TIMEOUT = 10000;

    private static CloseableHttpClient httpclient = HttpClients.createDefault();

    /**
     * 商户服务地址
     */
    private String serverUrl;

    /**
     * 服务商编号
     */
    private String agentId;

    /**
     * 服务商私钥
     */
    private String privateKey;

    /**
     * 请求超时时间，单位毫秒
     */
    private Integer timeout;

    /**
     * @param serverUrl  商户地址
     * @param agentId    服务商编号
     * @param privateKey 服务商私钥
     * @param timeout    毫秒
     */
    public LeshuaMerchantBillClientImpl(String serverUrl, String agentId, String privateKey, Integer timeout) {
        this.serverUrl = serverUrl;
        this.agentId = agentId;
        this.privateKey = privateKey;
        this.timeout = timeout;
    }

    /**
     * 调用商户相关请求
     *
     * @param request 商户入参
     * @param url     实际业务请求地址
     * @param timeout 超时设置，单位毫秒
     * @return
     * @throws LeshuaException
     */
    @Override
    public <T> LeshuaBillBaseResponse<T> execute(LeshuaBizRequest<T> request, String url, Integer timeout, String subAgentId) throws LeshuaException {
        ValidateUtil.validateWithThrow(request);
        String reqSerialNo = ReqSerialNoUtil.getReqSerialNo();
        //获取签名值
        String sign = SignUtil.getAgentVoiceSign(request, reqSerialNo, privateKey);

        String postUrl = serverUrl + url;

        //构建请求对象
        JSONObject object = new JSONObject();
        object.put("agentId", StrUtil.blankToDefault(subAgentId, agentId));
        object.put("reqSerialNo", reqSerialNo);
        object.put("sign", sign);
        object.put("version", SignUtil.DEFAULT_VERSION);
        object.put("data", request);

        RequestConfig requestConfig = null;
        if (timeout == null || timeout <= 0) {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
        } else {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout)
                    .setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        }


        HttpPost httpPost = new HttpPost(postUrl);
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            BasicResponseHandler handler = new BasicResponseHandler();
            StringEntity entity = new StringEntity(object.toJSONString(), "utf-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            String responseStr = httpClient.execute(httpPost, handler);
            log.info("乐刷请求返回  param={};response={}", JSON.toJSON(request), responseStr);
            JSONObject jsonObject = JSON.parseObject(responseStr);
            LeshuaBillBaseResponse<T> response = new LeshuaBillBaseResponse<>();
            response.setReqSerialNo(jsonObject.getString("reqSerialNo"));
            response.setErrorCode(jsonObject.getString("error_code"));
            response.setErrorMsg(jsonObject.getString("error_msg"));
            //获取翻页数据
            if (!StringUtils.isBlank(jsonObject.getString("page"))) {
                response.setPage(JSON.parseObject(jsonObject.getString("page"), LeshuaPage.class));
            }
            String data=jsonObject.getString("data");
            if (StringUtils.isBlank(data)) {
                return response;
            }
            response.setData(JSON.parseObject(jsonObject.getString("data"), request.getResponseClass()));
            return response;
        } catch (Exception e) {
            log.error("调用乐刷异常,request={};msg={}" ,JSON.toJSON(request), e.getMessage());
            throw new LeshuaException("调用失败", e);

        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                log.error("关闭httpClient出错，错误信息,request={};msg={}" ,JSON.toJSON(request), e.getMessage());
            }
        }
    }

    /**
     * 乐刷发票相关
     *
     * @param request 商户入参
     * @param url     实际业务请求地址
     * @param timeout 超时设置，单位毫秒
     * @return
     * @throws LeshuaException
     */
    @Override
    public <T> LeshuaBillBaseResponse<List<T>> executeList(LeshuaBizRequest<T> request, String url, Integer timeout, String subAgentId) throws LeshuaException {
        ValidateUtil.validateWithThrow(request);
        String reqSerialNo = ReqSerialNoUtil.getReqSerialNo();
        //获取签名值
        String sign = SignUtil.getAgentVoiceSign(request, reqSerialNo, privateKey);

        String postUrl = serverUrl + url;

        //构建请求对象
        JSONObject object = new JSONObject();
        object.put("agentId", StrUtil.blankToDefault(subAgentId, agentId));
        object.put("reqSerialNo", reqSerialNo);
        object.put("sign", sign);
        object.put("version", SignUtil.DEFAULT_VERSION);
        object.put("data", request);

        RequestConfig requestConfig = null;
        if (timeout == null || timeout <= 0) {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
        } else {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout)
                    .setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        }


        HttpPost httpPost = new HttpPost(postUrl);
        httpPost.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            BasicResponseHandler handler = new BasicResponseHandler();
            StringEntity entity = new StringEntity(object.toJSONString(), "utf-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            String responseStr = httpClient.execute(httpPost, handler);
            log.info("乐刷请求返回  param={};response={}", JSON.toJSON(request), responseStr);
            JSONObject jsonObject = JSON.parseObject(responseStr);
            LeshuaBillBaseResponse<List<T>> response = new LeshuaBillBaseResponse<>();
            response.setReqSerialNo(jsonObject.getString("reqSerialNo"));
            response.setErrorCode(jsonObject.getString("error_code"));
            response.setErrorMsg(jsonObject.getString("error_msg"));
            //获取翻页数据
            if (!StringUtils.isBlank(jsonObject.getString("page"))) {
                response.setPage(JSON.parseObject(jsonObject.getString("page"), LeshuaPage.class));
            }
            String data=jsonObject.getString("data");
            if (StringUtils.isBlank(data)) {
                return response;
            }
            response.setData(JSON.parseArray(jsonObject.getString("data"), request.getResponseClass()));
            return response;
        } catch (Exception e) {
            log.error("调用乐刷异常,request={};msg={}" ,JSON.toJSON(request), e.getMessage());
            throw new LeshuaException("调用失败", e);

        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                log.error("关闭httpClient出错，错误信息,request={};msg={}" ,JSON.toJSON(request), e.getMessage());
            }
        }
    }
}
